home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************/
- /* C O P Y R I G H T N O T I C E : */
- /* Copyright 1986 Eric Jul. May not be used for any */
- /* purpose without written permission from the author. */
- /**************************************************************************/
-
- /****************************************************************/
- /* Large Message Administration */
- /****************************************************************/
-
- #include <sys/types.h>
- #include <errno.h>
- #include <sys/file.h>
- #include <sys/ioctl.h>
-
- #include "Kernel/h/assert.h"
- #include "Kernel/h/macros.h"
- #include "Kernel/h/system.h"
- #undef integer
-
- #include "Kernel/h/mmTypes.h"
- #include "Kernel/h/mmCodes.h"
- #include "Kernel/h/mmMsgDefs.h"
- #include "Kernel/h/mmMsgTypes.h"
- #include "Kernel/h/mmEthrTypes.h"
- #include "Kernel/h/unixCodes.h"
- #include "Kernel/h/mmBufTypes.h"
- #include "Kernel/h/mmFifoTypes.h"
- #include "Kernel/h/kmdTypes.h"
- #include "Kernel/h/kEvents.h"
- #include "Kernel/h/lmTypes.h"
- #include "Kernel/h/lmCodes.h"
- #include "Kernel/h/hotsTypes.h"
-
- /*++BRDADDR++*/
- #include <net/if.h>
- /*--BRDADDR--*/
-
- #define endcase break
-
- extern int DisplayEdenMsg(),
- GetEdenMsg(),
- PutEdenMsg();
-
- /****************************************************************/
- /* */
- /* L A R G E M E S S A G E S */
- /* */
- /* The Large Message addition allows the transmission of */
- /* messages of unbounded size. */
- /* Messages are composed by passing references to the data to */
- /* a macro which in turn copies the data into messages and */
- /* sends it to another host. At the destination, the packets */
- /* making up the message are collected and when all packets */
- /* have been reliably received, then a handler for the message */
- /* is invoked. It is passed a handle through which it may */
- /* access the data by using a macro that will copy part or all */
- /* of the data into a given buffer. */
- /* The packets are allocated and deallocated by this module. */
- /* The packets are delivered reliably via MMSendMsg which uses */
- /* the reliable sliding window protocol implemetned in the */
- /* message module. */
- /* Only one message may be composed at a time (this is an */
- /* implementation restriction met by the Emerald Kernel). */
- /* */
- /* The packets are transmitted as they are filled although the */
- /* message is not delivered to the destination handler until */
- /* all the packets have been successfully delivered. */
- /* */
- /* Calling sequence: */
- /* LMStartMsg(&fHandle, MsgType, MsgSubtype, LNN ) */
- /* returns a handle */
- /* LMPutData(&fHandle, dataPtr, length) puts data into msg*/
- /* ... */
- /* LMSendMsg(&fHandle) completes the msg send */
- /* */
- /* Receiving sequence: */
- /* MMDefineMsgHandler(MsgType, MsgSubtype, Handler) */
- /* Handler(fHandle): */
- /* loop */
- /* LMGetData(&fHandle, dataPtr, length) */
- /* exit when length = 0 */
- /* <process data> */
- /* end loop */
- /* LMClose(&fHandle) */
- /* */
- /* The data may be reread any number of times by using */
- /* LMSeek(&fHandle, position, direction) */
- /* which works much like lseek of UNIX fame. */
- /* LMCurrentPosition(&fHandle) returns current byte pos */
- /* from the start of the file. */
- /* */
- /****************************************************************/
-
- /************************************************************/
- /* */
- /* LMStartMsg */
- /* */
- /* LMStartMsg allocates a long message and returns */
- /* a handle. The long message may only be accessed thru */
- /* */
- /************************************************************/
-
- KKStatus LMStartMsg(fHandle, fMsgType, fMsgSubtype, fLNN)
- LMHandle *fHandle;
- MessageType fMsgType;
- MessageSubtype fMsgSubtype;
- NodeNum fLNN;
- {
- KKStatus kstat;
- LMMsgPtr theMsg;
-
- KMDTrace("LM", 4, "New Long Msg to %d (0x%08x,0x%08x)\n",
- fLNN, fMsgType, fMsgSubtype);
- kstat = MMAllocateMsg(MAXMESSAGESIZE, (MessagePtr *)&theMsg);
- if (!mSUCCESS(kstat)) return kstat;
- MMBuildMsg((MessagePtr)theMsg, KMSG_LongMsg, LMM_LongMsg, fLNN,
- MAXMESSAGESIZE);
- theMsg->lmMsgHdr.ptr = (DataBytePtr) &theMsg->data[0];
- theMsg->lmMsgHdr.limit = ((DataBytePtr) theMsg->lmMsgHdr.ptr) +
- MAXLMMESSAGESIZE;
- theMsg->lmMsgHdr.realMsgType = fMsgType;
- theMsg->lmMsgHdr.realMsgSubtype = fMsgSubtype;
- theMsg->lmMsgHdr.flags.id = 1;
- theMsg->lmMsgHdr.flags.last = 0;
- *fHandle = theMsg;
- return LMS_Success;
- }
-
- /************************************************************/
- /* */
- /* LMPutLongData */
- /* */
- /* Places the data into a long msg specified by a handle. */
- /* The data may be any size. */
- /* */
- /************************************************************/
-
- KKStatus LMPutLongData(fHandle, fDataPtr, fDataLength)
- LMHandle *fHandle;
- DataBytePtr fDataPtr;
- unsigned int fDataLength;
- {
- KKStatus kstat;
- LMMsgPtr theMsg;
- register LMMsgHeaderPtr hdr, nextHdr;
- register int length = fDataLength;
- register int avail;
- DataBytePtr theData = fDataPtr;
- LMMsgPtr theNextMsg;
-
- KMDTrace("LM", 4, "LMPutLongData, handle=0x%08x, id %d, length %d\n",
- *fHandle, ((LMMsgPtr) *fHandle)->lmMsgHdr.flags.id, fDataLength);
-
- theMsg = *fHandle;
- hdr = &theMsg->lmMsgHdr;
- while (length > 0) {
- avail = (hdr->limit - hdr->ptr);
- KMDTrace("LM", 5, "avail = %d\n", avail);
- if (avail < length) {
- /* Did not fit */
- /* fill out packet, allocate a new packet, and send the old */
- bcopy((char *)theData, (char *)hdr->ptr, avail);
- hdr->ptr += avail;
- length -= avail;
- theData += avail;
- kstat = MMAllocateMsg(MAXMESSAGESIZE, (MessagePtr *)&theNextMsg);
- if (!mSUCCESS(kstat)) {
- ErrMsg("LMPutLongMsg: 0x%08x, (no memory)\n", kstat);
- assert(mSUCCESS(kstat));
- };
- MMBuildMsg((MessagePtr)theNextMsg, KMSG_LongMsg, LMM_LongMsg,
- theMsg->mmMsgHdr.MsgDest, MAXMESSAGESIZE);
- nextHdr = &theNextMsg->lmMsgHdr;
- nextHdr->ptr = (DataBytePtr) &theNextMsg->data[0];
- nextHdr->limit = ((DataBytePtr) theNextMsg->lmMsgHdr.ptr) +
- MAXLMMESSAGESIZE;
- nextHdr->flags.id = hdr->flags.id+1;
- nextHdr->flags.last = 0;
- KMDTrace("LM", 4, "Sending LongMsg packet #%d\n", hdr->flags.id);
- if (!mSUCCESS(kstat = MMSendMsg((MessagePtr) theMsg))) {
- ErrMsg("Cannot send LMMsg 0x%08x\n", kstat);
- };
- MMDeallocateMsg((MessagePtr) theMsg);
- theMsg = theNextMsg;
- *fHandle = theMsg;
- hdr = nextHdr;
- } else {
- /* Fit */
- KMDTrace("LM", 4, " packing %d bytes into packet\n", length);
- bcopy((char *)theData, (char *)hdr->ptr, length);
- hdr->ptr += length;
- length = 0;
- }
- }
- }
-
- /**********************************************************************/
- /* LMMsgHandler */
- /**********************************************************************/
-
- HResult LMMsgHandler(fMsg)
- LMMsgPtr fMsg;
- /* Put the packet into the queue and invoke the real handler if the packet
- was the last packet. */
- {
- KKStatus kstat;
- register LMMsgPtr theMsg = fMsg;
- register LMMsgHeaderPtr hdr = &theMsg->lmMsgHdr;
- register int length;
- LMHandle theFirstMsg;
- HOTSRecord *hotp;
-
- KMDTrace("LM", 4, "Long Msg packet (LNN %d, #%d) arrived\n",
- theMsg->mmMsgHdr.MsgSrc, hdr->flags.id);
- length = theMsg->mmMsgHdr.MsgSize - sizeof(LMMsgHeader);
- KMDTrace("LM", 5, " data length (excluding headers) = %d\n", length);
- hdr->ptr = &theMsg->data[0];
- hdr->limit = hdr->ptr + length;
-
- kstat = HOTSSearchPtr(theMsg->mmMsgHdr.MsgSrc, &hotp);
- if (!mSUCCESS(kstat)) {
- /* Hmm, it SHOULD be there. */
- ErrMsg(
- "Serious: Could not find LNN %d in HOTS table in LMMsgHandler\n",
- theMsg->mmMsgHdr.MsgSrc);
- return;
- }
-
- QueueIns(hotp->incomingLMQueue, theMsg, lmMsgHdr.next);
- if (hdr->flags.last) {
- KMDTrace("LM", 3, "LMMsg from #%d, total size %d bytes (+%d hdr)\n",
- theMsg->mmMsgHdr.MsgSrc,
- length + (hdr->flags.id - 1) * MAXLMMESSAGESIZE,
- sizeof(MessageHeader) + sizeof(LMMsgHeader));
- theFirstMsg = hotp->incomingLMQueue->lmMsgHdr.next;
- theFirstMsg->mmMsgHdr.MsgType = theFirstMsg->lmMsgHdr.realMsgType;
- theFirstMsg->mmMsgHdr.MsgSubtype =
- theFirstMsg->lmMsgHdr.realMsgSubtype;
- KMDTrace("LM", 5, "incomingQ 0x%08x, firstMsg 0x%08x\n",
- hotp->incomingLMQueue, theFirstMsg);
- QueueInit(hotp->incomingLMQueue);
- if (!mSUCCESS(kstat = MMDispatchMsg((MessagePtr) theFirstMsg))) {
- ErrMsg("Could not dispatch LM, status 0x%08x\n", kstat);
- LMClose(&theFirstMsg);
- return;
- };
- }
- }
-
-
- /**********************************************************************/
- /* LMSendMsg */
- /**********************************************************************/
-
- KKStatus LMSendMsg(fHandle)
- LMHandle *fHandle;
- /* Complete the last packet and send it. */
- {
- KKStatus kstat;
- LMMsgPtr theMsg = *fHandle;
- register LMMsgHeaderPtr hdr = &theMsg->lmMsgHdr;
-
- *fHandle =(LMHandle) NULL;
- KMDTrace("LM", 3,
- "Sending last LM packet (#%d), total msg size %d (+%d hdr)\n",
- hdr->flags.id, ((hdr->ptr - (&(theMsg->data[0]))) +
- ((hdr->flags.id - 1) * MAXLMMESSAGESIZE)),
- sizeof(MessageHeader) + sizeof(LMMsgHeader));
- hdr->flags.last = 1;
- /* Fix the size */
- theMsg->mmMsgHdr.MsgSize = (hdr->ptr - &theMsg->data[0]) +
- sizeof(LMMsgHeader);
- KMDTrace("LM", 4, " last packet size %d\n", theMsg->mmMsgHdr.MsgSize);
- kstat = MMSendMsg((MessagePtr) theMsg);
- if (!mSUCCESS(kstat)) {
- ErrMsg("LMSendMsg: bad kstat 0x%02x\n", kstat);
- }
- MMDeallocateMsg((MessagePtr) theMsg);
- return kstat;
- }
-
-
- /************************************************************/
-
- KKStatus LMBroadcastMsg(fHandle)
- LMHandle *fHandle;
- /* Send out a LM broadcast. Note: must be small enough !!! */
- {
- KKStatus kstat;
- LMMsgPtr theMsg = *fHandle;
- register LMMsgHeaderPtr hdr = &theMsg->lmMsgHdr;
- int totalSize;
-
- *fHandle =(LMHandle) NULL;
- totalSize = ((hdr->ptr - (&(theMsg->data[0]))) +
- ((hdr->flags.id - 1) * MAXLMMESSAGESIZE));
- KMDTrace("LM", 3, "Sending broadcast LMMsg packet, total size %d\n", totalSize);
- /* Check for max broadcast size */
- assert(totalSize < 1400);
- hdr->flags.last = 1;
- /* Fix the size */
- theMsg->mmMsgHdr.MsgSize = (hdr->ptr - &theMsg->data[0]) +
- sizeof(LMMsgHeader);
- kstat = MMBroadcastMsg((MessagePtr) theMsg);
- if (!mSUCCESS(kstat)) {
- ErrMsg("LMBroadcastMsg: bad kstat 0x%02x\n", kstat);
- }
- MMDeallocateMsg((MessagePtr) theMsg);
- return kstat;
- }
-
-
- /************************************************************/
-
- void LMGetLongData(fHandle, fDataPtr, fDataLength)
- LMHandle *fHandle;
- DataBytePtr fDataPtr;
- unsigned int *fDataLength;
- /* Get a chunk of data out of one (or more) LM packets. */
- {
- LMMsgPtr theMsg;
- register LMMsgHeaderPtr hdr, nextHdr;
- int sum = 0;
- register int length = *fDataLength;
- register unsigned int avail;
- DataBytePtr theData = fDataPtr;
- LMMsgPtr theNextMsg;
-
- KMDTrace("LM", 4, "LMGetLongData, handle=0x%08x, id %d, length %d\n",
- *fHandle, (*fHandle)->lmMsgHdr.flags.id, *fDataLength);
-
- theMsg = *fHandle;
- assert(theMsg != NULL);
- hdr = &theMsg->lmMsgHdr;
- while (length > 0) {
- avail = (hdr->limit - hdr->ptr);
- KMDTrace("LM", 4, "avail = %d\n", avail);
- if (avail < length) {
- /* Not enough data in this buffer */
- bcopy((char *)hdr->ptr, (char *)theData, (int)avail);
- hdr->ptr += avail;
- length -= avail;
- theData += avail;
- sum += avail;
-
- if(hdr->flags.last){
- *fDataLength = sum;
- return;
- }
-
- theNextMsg = hdr->next;
- nextHdr = &theNextMsg->lmMsgHdr;
- nextHdr->ptr = (DataBytePtr) &theNextMsg->data[0];
- nextHdr->limit = ((DataBytePtr) nextHdr) +
- theNextMsg->mmMsgHdr.MsgSize;
- KMDTrace("LM", 4, "Opening LMpacket #%d, size %d\n", hdr->flags.id,
- nextHdr->limit - nextHdr->ptr);
- theMsg = theNextMsg;
- *fHandle = theMsg;
- hdr = nextHdr;
- } else {
- /* Fit */
- bcopy((char *)hdr->ptr, (char *)theData, length);
- hdr->ptr += length;
- sum += length;
- length = 0;
- }
- }
- *fDataLength = sum;
- }
-
- long LMCurrentPosition(fHandle)
- LMHandle *fHandle;
- {
- register long current;
- register LMHandle theMsg = *fHandle;
-
- current = (theMsg->lmMsgHdr.ptr - &theMsg->data[0] ) +
- (theMsg->lmMsgHdr.flags.id - 1) * MAXLMMESSAGESIZE;
- KMDTrace("LM", 3, "LMCurrentPosition %d\n", current);
- return(current);
- }
-
- KKStatus LMSeek(fHandle, fPosition, fDirection)
- LMHandle *fHandle;
- long fPosition, fDirection;
- /* Seek as for lseek, fDirection: 0: from start, 1: relative, 2: from end */
- {
- long current, desired, wantId, desiredLocalPosition;
- LMHandle theMsg = *fHandle;
-
- current = theMsg->lmMsgHdr.ptr -
- (DataBytePtr) theMsg->data[0] +
- (theMsg->lmMsgHdr.flags.id - 1) * MAXLMMESSAGESIZE;
- KMDTrace("LM", 3, "LMSeek current pos %d, offset %d\n", current,
- fPosition);
-
- switch ((int)fDirection) {
- case 0: /* Offset from start of msg */
- desired = fPosition;
- break;
-
- case 1: /* Offset from current Position */
- desired = current + fPosition;
- break;
-
- case 2: /* Offset form end of file */
- assert(FALSE);
- break;
-
- default:
- assert(FALSE);
- }
- wantId = (desired / MAXLMMESSAGESIZE) +1;
- desiredLocalPosition = desired % MAXLMMESSAGESIZE;
- KMDTrace("LM", 4, "Seeking msgId %d, position %d\n", wantId,
- desiredLocalPosition);
- for(;theMsg->lmMsgHdr.flags.id != wantId; theMsg = theMsg->lmMsgHdr.next);
- theMsg->lmMsgHdr.ptr = &theMsg->data[desired % MAXLMMESSAGESIZE];
- }
-
- /************************************************************************/
- void LMClose(fHandle)
- LMHandle *fHandle;
- {
- LMHandle theNextMsg, firstDealloced, theMsg = *fHandle;
- int id;
-
- KMDTrace("LM", 4, "Finished with Long Msg\n");
- firstDealloced = theMsg;
- do {
- theNextMsg = theMsg->lmMsgHdr.next;
- id = theMsg->lmMsgHdr.flags.id;
- KMDTrace("LM", 5, "Deallocate packet #%d\n", id);
- MMDeallocateMsg((MessagePtr) theMsg);
- theMsg = theNextMsg;
- } while (theNextMsg != firstDealloced);
- *fHandle = NULL;
- }
-
- /************************************************************/
-
- void LMInit()
- {
- KMDSetTrace(LM);
-
- KMDTrace("LM", 5,
- "LMInit Byte sizes MMHdr:%d, LMHdr%d, max useful in packet %d\n",
- sizeof(MessageHeader), sizeof(LMMsgHeader), MAXLMMESSAGESIZE);
- MMDefineMsgHandler(KMSG_LongMsg, LMM_LongMsg, (HandlerPtr)LMMsgHandler,
- (HandlerPtr *)NULL);
- }
-
-
- /************************************************************/
- /* E N D O F L A R G E M E S S A G E */
- /************************************************************/
-